{% extends "subscribe-form.html" %}
{% load static sekizai_tags djng_tags tutorial_tags %}

{% block addtoblock %}
	{{ block.super }}
	{% addtoblock "ng-config" %}['$httpProvider', function($httpProvider) { $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; $httpProvider.defaults.headers.common['X-CSRFToken'] = '{{ csrf_token }}'; }]{% endaddtoblock %}
{% endblock addtoblock %}

{% block main-intro %}
<h1>Server-Side Form Validation</h1>
<p class="lead">Django Form's two-way data-binding with an AngularJS controller</p>
<p><span class="label label-warning">New in version 2.0</span>&emsp;This example shows how to reflect Django's form data into an AngularJS controller.</p>
{% endblock main-intro %}

{% block form_tag %}name="{{ form.form_name }}" method="post" action="." djng-endpoint="." ng-model-options="{allowInvalid: true}" novalidate{% endblock %}

{% block form_submission %}
	<button type="submit" class="btn btn-primary">Submit via Post</button><span>&nbsp;</span>
	<button type="button" class="btn btn-primary" ng-click="do(update()).then(redirectTo()).catch(scrollToRejected())">Submit via Ajax</button>
{% endblock %}

{% block form_foot %}
	{% verbatim %}
		<h5>Scope:</h5>
		<pre>subscribe_data = {{ subscribe_data | json }}</pre>
	{% endverbatim %}
{% endblock form_foot %}

{% block main-tutorial %}
<p>When working with Django Forms and AngularJS, it is a common use case to upload the form's model
data to an endpoint on the server. If the directive <code>ng-model</code> is added to an input
field, then, thanks to AngularJS's two-way databinding, the <code>scope</code> object contains a
copy of the actual input field's content.</p>

<h5>Auto-adding <code>ng-model</code> to forms</h5>
<p>If a form inherits from the mixin class <code>NgModelFormMixin</code>, then
<strong>django-angular</strong> renders each field with the directive
<nobr><code>ng-model="<em>fieldname</em>"</code></nobr>. To prevent polluting the scope's
namespace, it is common practice to encapsulate all the form fields into a separate JavaScript
object. The name of this encapsulating object can be set during the form definition, using the
class member <code>scope_prefix</code>. Furthermore, set the class member <code>form_name</code>
to a different name. If omitted, the mixin class will invent a unique form name for you. The
<code>form_name</code> <em>must</em> be different from <code>scope_prefix</code>, because
AngularJS's internal form controller adds its own object to the scope, and this objects is
named after the form. To prevent confusion, name your forms ending in something such as
<nobr><code>&hellip;_form</code></nobr>, whereas the form's models shall be kept inside an object ending in
<nobr><code>&hellip;_data</code></nobr>.

<p>In this example, an additional server-side validations has been added to the form: The method
<code>clean()</code> rejects the combination of “John” and “Doe” for the first- and last name
respectively. Errors for a failed form validation are send back to the client and displayed on top
of the form.</p>

<h5>Using directive <code>djng-endpoint</code></h5>
<p>We must inform the client where we want the form data to be sent. For this purpose,
<strong>django-angular</strong> offers the attribute directive
<nobr><code>&lt;form djng-endpoint="/path/to/endpoint"&gt;</code></nobr>. This is the Ajax's
counterpart of the <nobr><code>action="&hellip;"</code></nobr> form attribute.</p>

<h5>Error responses</h5>
<p>Form data submitted by Ajax, is validated by the server using the same functionality as if it
would have been submitted using the classic <nobr><code>application/x-www-form-urlencoded</code></nobr>
POST submission. Errors detected during such a validation, are sent back to the client using a
JSON object. This object for example, is structured such as:
<code>{"<em>formname</em>": {"errors": {"<em>fieldname1</em>": ["This field is required."]},
"__all__": ["The combination of username and password is not correct."]}}}</code>. Just as
in Django, the <code>__all__</code> is used for form errors not associated with a certain field.
Such an error, typically is rendered on top of the form.</p>

<h5>Populating the form</h5>
<p>Sometimes it is desirable to use an Ajax request to prefill all or a subset of the form fields with
values. Whenever the Django endpoint adds an object such as <code>{"<em>formname</em>": {"models":
{"<em>fieldname1</em>": "Some value", "fieldname2": "Other value"}}}</code> to the response object,
then the <strong>django-angular</strong> form-controller adds those values to the form's input
fields.</p>

<h5>Forms Submission</h5>
<p>The submit button(s) must be placed anywhere inside the <code>&lt;form&gt;&hellip;&lt;/form&gt;</code>
element. To send the form's content to the server, add <nobr><code>ng-click="do(update())"</code></nobr>
to the submission button. We have to start this expression with <code>do(&hellip;)</code>, in order to
emulate the first promise, see below.</p>

<p>By itself, <code>do(update())</code> would just send the data to the server, but not invoke any
further action on the client. We therefore must tell our directive, what we want to do next. For
this purpose, <strong>django-angular</strong>'s button directive offers a few prepared targets,
which all can be chained in any order. If we change the above to
<nobr><code>ng-click="do(update()).then(reloadPage())"</code></nobr>, then after a successful
submission the current page is reloaded. This is explained in detail in the next example.</p>


<p ng-init="tabList=['Form', 'View', 'HTML']"></p>
{% endblock main-tutorial %}

{% block main-sample-code %}
{% autoescape off %}
<div ng-show="activeTab==='Form'">{% pygments "forms/model_scope.py" %}</div>
<div ng-show="activeTab==='View'">{% pygments "views/model_scope.py" %}</div>
<div ng-show="activeTab==='HTML'">{% pygments "tutorial/model-scope.html" %}</div>
{% endautoescape %}

{% verbatim %}
<p class="bg-info"><strong>Note: </strong>The AngularJS app is configured inside Django's HTML
template code, since template tags, such as <code>{&#8203;{&nbsp;csrf_token&nbsp;}&#8203;}</code> can't be
expanded in pure JavaScript.</p>
{% endverbatim %}

{% endblock main-sample-code %}
